package com.anxin.act.process.service;

import com.alibaba.fastjson.JSONObject;
import com.anxin.act.busFlow.entity.WfBusNode;
import com.anxin.act.busFlow.entity.WfConfigNode;
import com.anxin.act.busFlow.service.WfBusNodeService;
import com.anxin.act.busFlow.service.WfConfigNodeService;
import com.anxin.act.process.dao.ActProcessDao;
import com.anxin.act.process.inter.ProcessStart;
import com.anxin.act.utils.ActUtils;
import com.anxin.common.utils.StringUtils;
import com.anxin.common.utils.dict.DictUtils;
import com.anxin.framework.redis.MqProducer;
import com.anxin.framework.redis.RedisMq;
import com.anxin.framework.web.entity.AjaxResult;
import com.anxin.sys.file.entity.FileBase;
import com.anxin.sys.file.service.FileBaseService;
import com.anxin.sys.filefolder.entity.FileFolder;
import com.anxin.sys.filefolder.service.FileFolderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 流程启动前
 * @author: liuxiangyu
 * @date: 2020/7/16 12:18
 */
@Service
public class ProcessStartService implements RedisMq {

    @Autowired
    private ActProcessDao actProcessDao;

    @Autowired
    private WfBusNodeService wfBusNodeService;

    @Autowired
    private WfConfigNodeService wfConfigNodeService;

    @Autowired
    private FileBaseService fileBaseService;

    @Autowired
    private FileFolderService fileFolderService;

    @Autowired
    private MqProducer mqProducer;

    @Autowired
    ApplicationContext context;



    /**
     * 流程启动前校验
     * @param dataTable
     * @param dataId
     * @return
     */
    public AjaxResult startCheck(String dataTable, String dataId){
        //查询流程当前审批状态
        String dataStatus = actProcessDao.getDataStatus(dataTable, dataId);
        //如果流程状态为待审批或审批完成则不可启动流程
        if ("D".equals(dataStatus) || "W".equals(dataStatus)){
            return AjaxResult.error("流程状态为《"+ DictUtils.getDictLabel(dataStatus,"work_flow_status","") +"》不可启动流程");
        }

        if ("wf_bus_node".equals(dataTable)){
            // 校验是否上传了必须要传的附件
            String checkFileMessage = this.checkFile(dataTable, dataId);
            if (StringUtils.isNotBlank(checkFileMessage)){
                return AjaxResult.error("流程启动失败,请上传附件"+checkFileMessage);
            }

            // 查询流程依赖
            String checkRelyNodeMessage = this.checkRelyNode(dataId);
            if (StringUtils.isNotBlank(checkRelyNodeMessage)){
                return AjaxResult.error("流程启动失败,请先完成"+checkRelyNodeMessage);
            }

        }

        return AjaxResult.success();
    }

    /**
     * 检查流程依赖节点
     * @param dataId wfBusNode表ID
     * @return 校验信息
     */
    public String checkRelyNode(String dataId){
        StringBuffer res = new StringBuffer();
        WfBusNode currentWfBusNode = wfBusNodeService.get(dataId);
        WfConfigNode currentWfConfigNode = wfConfigNodeService.get(currentWfBusNode.getNodeId());
        if (currentWfConfigNode.getRelyNode() != null && currentWfConfigNode.getRelyNode().size() > 0){
            for (int i = 0; i < currentWfConfigNode.getRelyNode().size(); i++) {
                String wfBusConfigNodeId = currentWfConfigNode.getRelyNode().getString(i);
                WfBusNode wfBusNode = new WfBusNode(currentWfBusNode.getBusId(),wfBusConfigNodeId,new String[]{"W","H"});
                List<WfBusNode> wfBusNodeList = wfBusNodeService.findList(wfBusNode);
                if (wfBusNodeList.size() == 0){
                    WfConfigNode wfConfigNode = wfConfigNodeService.get(wfBusConfigNodeId);
                    StringUtils.bufferAppend(res,"「"+wfConfigNode.getNodeName()+"」",",");
                }
            }
        }

        return res.toString();
    }


    /**
     * 校验业务流程必须要上传的附件
     * @param dataTable
     * @param dataId
     * @return
     */
    public String checkFile(String dataTable,String dataId){
        StringBuffer res = new StringBuffer();
        if ("wf_bus_node".equals(dataTable)){
            WfBusNode wfBusNode = wfBusNodeService.get(dataId);
            WfConfigNode wfConfigNode = wfConfigNodeService.get(wfBusNode.getNodeId());
            if (wfConfigNode.getCheckFile() != null && wfConfigNode.getCheckFile().size() > 0){
                // 当前表单上次过的附件
                List<FileBase> fileList = fileBaseService.findList(wfBusNode.getDataId(), null);
                Map<String,String> fileDirMap = new HashMap<>();

                for (FileBase fileBase : fileList) {
                    // 确保附件已经上传，不是只保存了附件记录
                    if (StringUtils.isNotBlank(fileBase.getMD5())){
                        if (StringUtils.isNotBlank(fileBase.getName()) && StringUtils.isNotBlank(fileBase.getDirectoryId())){
                            FileFolder fileLibrary = fileFolderService.get(fileBase.getDirectoryId());
                            if (StringUtils.isNotBlank(fileLibrary.getId())){
                                fileDirMap.put(fileLibrary.getId(),fileBase.getName());
                            }
                        }
                    }

                }


                for (int i = 0; i < wfConfigNode.getCheckFile().size(); i++) {
                    String checkFileId = wfConfigNode.getCheckFile().getString(i);
                    FileFolder fileLibrary = fileFolderService.getById(checkFileId);
                    if (fileLibrary != null && fileDirMap.get(checkFileId) == null){
                        StringUtils.bufferAppend(res,"「"+fileLibrary.getName()+"」",",");
                    }
                }
            }

        }
        return res.toString();
    }

    /**
     * 流程启动后执行
     * @param dataTable 数据表名
     * @param dataId 数据ID
     * @param actId 流程ID
     */
    public void startEnd(String dataTable,String dataId,String actId){
        JSONObject messageJson = new JSONObject();
        messageJson.put("dataTable",dataTable);
        messageJson.put("dataId",dataId);
        messageJson.put("actId",actId);
        mqProducer.sendMessage(ProcessStartService.class,messageJson.toString());

    }

    /**
     * 消费流程流程结束后执行的方法
     * @param message
     * @return
     */
    @Override
    public boolean onMessage(String message) {
        JSONObject messageJson = JSONObject.parseObject(message);
        String dataTable = messageJson.getString("dataTable");
        String dataId = messageJson.getString("dataId");
        String actId = messageJson.getString("actId");

        if ("wf_bus_node".equals(dataTable)){
            Map<String, String> dataTableAndDataId = ActUtils.getDataTableAndDataId(actId);
            dataId = dataTableAndDataId.get("actDataId");
            dataTable = dataTableAndDataId.get("actDataTable");
        }

        // 调用业务功能结束后需要执行的方法
        this.businessStart(dataTable,dataId,actId);

        return true;
    }

    /**
     * 调用业务启动后需要执行的方法
     * @param dataTable 业务表名
     * @param dataId 业务ID
     * @param actId 流程实例ID
     */
    public void businessStart(String dataTable,String dataId,String actId){
        Map<String, ProcessStart> beansMap = context.getBeansOfType(ProcessStart.class);
        List<String> hiBeanKey = new ArrayList<>();
        for (String beanKey : beansMap.keySet()) {
            if (!hiBeanKey.contains(beanKey)) {
                ProcessStart processStart = beansMap.get(beanKey);
                processStart.processStart(dataTable,dataId,actId);
                hiBeanKey.add(beanKey);
            }
        }
    }
}
